package org.luxor.commons.mqtt.config;

import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.luxor.commons.mqtt.annotation.MqttTopicListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.Environment;
import org.springframework.util.PropertyPlaceholderHelper;


/**
 * 注册Mqtt主题订阅消息接收器
 *
 * @author Mr.yan @date 2019/10/13
 */
public class MqttTopicListenerRegistrar implements BeanPostProcessor {
    private static final Logger logger = LoggerFactory.getLogger(MqttTopicListenerRegistrar.class);

    private static final PropertyPlaceholderHelper placeholderHelper = new PropertyPlaceholderHelper("${", "}", ":", false);

    private final Environment environment;
    private final MqttClient client;

    public MqttTopicListenerRegistrar(Environment environment, MqttClient client) {
        this.environment = environment;
        this.client = client;
    }


    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        MqttTopicListener annotation = AnnotationUtils.findAnnotation(bean.getClass(), MqttTopicListener.class);
        if (annotation != null && methodRequire(bean)) {
            try {
                String topicName = placeholderHelper.replacePlaceholders(annotation.topicName(), environment::getProperty);
                client.subscribe(topicName, annotation.qos(), (IMqttMessageListener) bean);
                logger.info("Initialize subscribe, topicName:{} qos:{}", topicName, annotation.qos());
            } catch (MqttException e) {
                logger.error("Initialize subscribe, Fail", e);
            }
        }
        return bean;
    }

    private boolean methodRequire(Object receiver) {
        try {
            receiver.getClass().getDeclaredMethod("messageArrived", String.class, MqttMessage.class);
        } catch (NoSuchMethodException e) {
            logger.warn("事件接收者:[ {} ]中,没实现准确的接收方法. -> [public void messageArrived (String topic, MqttMessage message)]", receiver.getClass());
            return false;
        }
        return true;
    }

}